package repo

import (
	"context"
	"errors"
	"strconv"

	"admin_template/bff/admin/internal/base/data"
	"admin_template/bff/admin/internal/entity/ent/sysapi"
	"admin_template/bff/admin/internal/schema"
	"admin_template/bff/admin/internal/service"
	"gitee.com/byx_darwin/go-tools/kitex/rpc_error"
	pkgErrors "github.com/pkg/errors"
)

type enforcerRepo struct {
	*data.Data
}

func NewSysEnforcerRepo(d *data.Data) service.EnforcerRepo {
	return &enforcerRepo{d}
}

func (repo *enforcerRepo) Del(roleID int64) error {
	_, err := repo.Enforcer.RemoveFilteredPolicy(0, strconv.Itoa(int(roleID)))
	if err != nil {
		return err
	}
	_ = repo.Enforcer.InvalidateCache()
	return nil
}

func (repo *enforcerRepo) UpdateApi(old, new schema.EnforcerInfo) error {
	oldPolicy := []string{old.Path, old.Method}
	newPolicy := []string{new.Path, new.Method}
	_, err := repo.Enforcer.UpdatePolicy(oldPolicy, newPolicy)
	if err == nil {
		_ = repo.Data.Enforcer.InvalidateCache()
	}
	return err
}
func (repo *enforcerRepo) Update(roleID int64, list []schema.EnforcerInfo) error {
	authorityId := strconv.Itoa(int(roleID))
	_, err := repo.Enforcer.RemoveFilteredPolicy(0, authorityId)
	if err != nil {
		return err
	}
	rules := make([][]string, 0, len(list))
	for _, v := range list {
		rules = append(rules, []string{authorityId, v.Path, v.Method})
	}
	success, _ := repo.Data.Enforcer.AddPolicies(rules)

	if !success {
		err = pkgErrors.New("存在相同api,添加失败,请联系管理员")
		return pkgErrors.Wrap(err, "API更新:")
	}
	_ = repo.Data.Enforcer.InvalidateCache()
	return nil
}
func (repo *enforcerRepo) Enforce(sub, obj, act string) error {
	isMatch, err := repo.Data.Enforcer.Enforce(sub, obj, act)
	if err != nil {
		return rpc_error.NewBizStatusError(rpc_error.ErrorTypeSqlExecFailure, err)
	}
	if isMatch {
		return nil
	} else {
		err = pkgErrors.New("无权限")
		return rpc_error.NewBizStatusError(rpc_error.ErrorTypeDataInvalid,
			pkgErrors.Wrap(err, "API权限验证:"))
	}
}

func (repo *enforcerRepo) Get(roleID int64) ([]schema.EnforcerInfo, error) {
	authorityId := strconv.Itoa(int(roleID))
	list, err := repo.Enforcer.GetFilteredPolicy(0, authorityId)
	if err != nil {
		return nil, err
	}
	enforcerList := make([]schema.EnforcerInfo, 0, len(list))
	for _, value := range list {
		info := schema.EnforcerInfo{
			Path:   value[1],
			Method: value[2],
		}
		enforcerList = append(enforcerList, info)

	}
	return enforcerList, nil
}

func (repo *enforcerRepo) Init(ctx context.Context) error {
	list, err := repo.DB.SysApi.
		Query().Where(sysapi.DeleteTimeIsNil()).All(ctx)
	if err != nil {
		return err
	}
	rules := make([][]string, 0, len(list))
	for _, v := range list {
		rules = append(rules, []string{"1", v.Path, v.Method})
	}
	success, _ := repo.Data.Enforcer.AddPolicies(rules)
	if !success {
		return errors.New("存在相同api,添加失败,请联系管理员")
	}
	_ = repo.Data.Enforcer.InvalidateCache()
	return nil

}
